<script setup>
import { ref, computed } from 'vue'

const props = defineProps({
  direction: {
    type: String,
    default: 'vertical',
    validator: (value) => ['vertical', 'horizontal'].includes(value)
  },
  reverse: {
    type: Boolean,
    default: false
  },
  timestamp: {
    type: String,
    required: true
  },
  type: {
    type: String,
    default: 'primary',
    validator: (value) => ['primary', 'success', 'warning', 'danger', 'info'].includes(value)
  },
  color: {
    type: String,
    validator: (value) => /^(#|rgb|hsl|hsv)/.test(value)
  },
  size: {
    type: String,
    default: 'normal',
    validator: (value) => ['normal', 'large'].includes(value)
  },
  icon: {
    type: String,
    default: ''
  }
})

const timelineItems = ref([
  { id: 1, timestamp: '2024-01-01', content: '项目启动', type: 'primary' },
  { id: 2, timestamp: '2024-02-15', content: '开发阶段', type: 'warning' },
  { id: 3, timestamp: '2024-03-20', content: '测试完成', type: 'success' },
  { id: 4, timestamp: '2024-04-10', content: '正式发布', type: 'info' }
])

const nodeStyle = computed(() => {
  const style = {}
  if (props.color) {
    style.backgroundColor = props.color
  }
  if (props.size === 'large') {
    style.width = '16px'
    style.height = '16px'
  }
  return style
})

const containerClass = computed(() => ({
  'timeline-container': true,
  'is-horizontal': props.direction === 'horizontal',
  'is-reverse': props.reverse
}))
</script>

<template>
  <div :class="containerClass">
    <div v-for="(item, index) in timelineItems"
         :key="item.id"
         class="timeline-item"
    >

      <div class="timeline-node"
           :class="[`is-${type}`, size]"
           :style="nodeStyle"
      >
        <i v-if="icon" :class="icon"></i>
        <slot name="dot" v-else></slot>
      </div>
      <div class="timeline-line"
           :class="{
             'is-first': index === 0,
             'is-last': index === timelineItems.length - 1,
             'is-horizontal': props.direction === 'horizontal'
           }"
      ></div>

      <div class="timeline-content">
        <div class="timeline-timestamp">{{ timestamp }}</div>
        <div class="timeline-content-inner">
          <slot>{{ item.content }}</slot>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.timeline-container {
  position: relative;
  padding: 20px 0;
}

.timeline-item {
  position: relative;
  display: flex;
  margin-bottom: 20px;
}

.timeline-line {
  position: absolute;
  background-color: #E4E7ED;
  z-index: 1;
}

.timeline-line:not(.is-horizontal) {
  left: 5px;
  top: -10px;
  width: 2px;
  height: calc(100% + 20px);
}

.large+.timeline-line:not(.is-horizontal) {
  left: 7px;
}

.timeline-line.is-horizontal {
  left: 0;
  top: 5px;
  width:100%;
  height: 2px;
}

.timeline-line.is-first:not(.is-horizontal) {
  top: 0;
}

.timeline-line.is-horizontal.is-first {
  left: 0;
}

.timeline-line.is-last:not(.is-horizontal) {
  height: calc(50% - 10px);
  transform: translateY(-50%);
}

.timeline-line.is-horizontal.is-last {
  width: 50%;
  transform: translateX(-100%);
}

.timeline-node {
  position: relative;
  z-index: 2;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background-color: #409EFF;
  flex-shrink: 0;
  margin-right: 16px;
}

.timeline-node.large {
  width: 16px;
  height: 16px;
}

.timeline-node.is-primary { background-color: #409EFF; }
.timeline-node.is-success { background-color: #67C23A; }
.timeline-node.is-warning { background-color: #E6A23C; }
.timeline-node.is-danger { background-color: #F56C6C; }
.timeline-node.is-info { background-color: #909399; }

.timeline-content {
  flex: 1;
  padding: 0 16px;
}

.timeline-timestamp {
  font-size: 13px;
  color: #909399;
  margin-bottom: 8px;
}

.timeline-content-inner {
  background-color: #F5F7FA;
  padding: 12px;
  border-radius: 4px;
}

.is-horizontal {
  display: flex;
}

.is-horizontal .timeline-item {
  flex-direction: column;
  flex: 1;
  padding-right: 20px;
  margin-bottom: 0;
}

.is-reverse {
  flex-direction: row-reverse;
}

.is-reverse .timeline-item {
  flex-direction: column-reverse;
}
</style>